﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace Engine.Graphics
{
    public enum CameraMode { Free, Follow }
    public class Camera : Component
    {
        #region Field Region
        float speed;
        float zoom;
        CameraMode mode;
        #endregion
        #region Property Region

        public Matrix Transformation
        {
            get
            {
                return Matrix.CreateScale(zoom) *
                    Matrix.CreateTranslation(new Vector3((int)Math.Floor(-gameObject.transform.WorldPosition.X), (int)Math.Floor(-gameObject.transform.WorldPosition.Y), 0f));
            }
        }

        public float Speed
        {
            get { return speed; }
            set
            {
                speed = (float)MathHelper.Clamp(speed, 1f, 16f);
            }
        }
        public float Zoom
        {
            get { return zoom; }
        }
        public CameraMode CameraMode
        {
            get { return mode; }
        }

        public Color ClearColor { get; set; }
        #endregion
        #region Constructor Region
        public Camera()
        {
            speed = 4f;
            zoom = 1f;
            mode = CameraMode.Follow;
            ClearColor = Color.Black;
        }

        public Camera(Color _clearColor) : this()
        {
            speed = 4f;
            zoom = 1f;
            mode = CameraMode.Follow;
            ClearColor = _clearColor;
        }

        public override void OnAdd(GameObject _gameObject)
        {
            base.OnAdd(_gameObject);
            gameObject.camera = this;
            if (GraphicsEngine.Instance.MainCamera == null)
                GraphicsEngine.Instance.MainCamera = this;
        }

        public override void OnRemove()
        {
            base.OnRemove();
            gameObject.camera = null;
            if (GraphicsEngine.Instance.MainCamera == this)
                GraphicsEngine.Instance.MainCamera = null;
        }

        #endregion
        #region Method Region
        public override void Update(GameTime gameTime)
        {
            if (mode == CameraMode.Follow)
                return;
            Vector2 motion = Vector2.Zero;

            if (InputHandler.KeyDown(Keys.Left) ||
                InputHandler.ButtonDown(Buttons.RightThumbstickLeft, PlayerIndex.One))
                motion.X = -1;
            else if (InputHandler.KeyDown(Keys.Right) ||
                     InputHandler.ButtonDown(Buttons.RightThumbstickRight, PlayerIndex.One))
                motion.X = 1;

            if (InputHandler.KeyDown(Keys.Up) ||
                InputHandler.ButtonDown(Buttons.RightThumbstickUp, PlayerIndex.One))
                motion.Y = -1;
            else if (InputHandler.KeyDown(Keys.Down) ||
                     InputHandler.ButtonDown(Buttons.RightThumbstickDown, PlayerIndex.One))
                motion.Y = 1;


            if (motion != Vector2.Zero)
            {
                motion.Normalize();
                gameObject.transform.WorldPosition += motion * speed * (float)gameTime.ElapsedGameTime.TotalSeconds * 60f;
            }

        }
        public void ZoomIn()
        {
            zoom += .25f;
            if (zoom > 2.5f)
                zoom = 2.5f;
            Vector2 newPosition = gameObject.transform.WorldPosition * zoom;

            SnapToPosition(newPosition);
        }
        public void ZoomOut()
        {
            zoom -= .25f;
            if (zoom < .25f)
                zoom = .25f;
            Vector2 newPosition = gameObject.transform.WorldPosition * zoom;
            SnapToPosition(newPosition);
        }
        private void SnapToPosition(Vector2 newPosition)
        {
            gameObject.transform.WorldPosition = newPosition - GraphicsEngine.Instance.Resolution / 2;
        }
        public void ToggleCameraMode()
        {
            if (mode == CameraMode.Follow)
                mode = CameraMode.Free;
            else if (mode == CameraMode.Free)
                mode = CameraMode.Follow;
        }

        public Vector2 WorldToScreen(Vector2 _worldPos)
        {
            return _worldPos - gameObject.transform.WorldPosition * zoom;
        }

        public Vector2 ScreenToWorld(Vector2 _screenPos)
        {
            return _screenPos + gameObject.transform.WorldPosition * zoom;
        }

        public Rectangle WorldToScreen(Rectangle _worldPos)
        {
            return new Rectangle((int)(_worldPos.X - Position.X), (int)(_worldPos.Y - Position.Y), _worldPos.Width, _worldPos.Height);
        }

        public Rectangle ScreenToWorld(Rectangle _screenPos)
        {
            return new Rectangle((int)(_screenPos.X + Position.X), (int)(_screenPos.Y + Position.Y), _screenPos.Width, _screenPos.Height);
        }
        #endregion
    }
}
